// Copyright (C) joyinter
// All rights reserved.
// 
// Author : Jiang Li
// Date   : 2005-4-30

#include "stdafx.h"
#include "csumpefile.h"
#include "crc.h"

namespace JoyGuard
{

//##ModelId=44C4B60E00DB
bool CSumPeFile::BuildSectCSum(
    const BYTE* baseAddr, const char* sectName, CSumSect& ss)
{
    // get dos header
    IMAGE_DOS_HEADER* dosHeader    = (IMAGE_DOS_HEADER*)baseAddr;
    if(dosHeader->e_magic != IMAGE_DOS_SIGNATURE)
    {
        return NULL;
    }
    if(dosHeader->e_lfanew <= 0)
    {
        return false;
    }

    // get nt headers
    IMAGE_NT_HEADERS* ntheaders   = (IMAGE_NT_HEADERS*)(baseAddr+dosHeader->e_lfanew);
    if(ntheaders->Signature != IMAGE_NT_SIGNATURE)
    {
        return false;
    }

    // find a section match the sectName
    int sectCount = ntheaders->FileHeader.NumberOfSections;
    IMAGE_SECTION_HEADER* sectheaders = (IMAGE_SECTION_HEADER*)(ntheaders+1);
    IMAGE_SECTION_HEADER* foundHeader = NULL;
    for(int i = 0; i < (int)sectCount; i ++)
    {
        IMAGE_SECTION_HEADER* header = sectheaders+i;
        if(header->Characteristics == 0)
        {
            return false;
        }
        if(strcmp((char*)header->Name, sectName) == 0)
        {
            foundHeader = header;
            break;
        }
    }
    if(foundHeader == NULL)
    {
        return false;
    }

    ss.m_rva = foundHeader->VirtualAddress;
    ss.m_size= foundHeader->Misc.VirtualSize;

    const BYTE* sectBuf = baseAddr+foundHeader->PointerToRawData;
    Crc csum;
    csum.Update(sectBuf, ss.m_size);
    ss.m_csum = csum.Final();

    return true;
}

//##ModelId=44C4B60E00EB
bool CSumPeFile::BuildSectCSum(
    const char* peFile, const char* sectName, CSumSect& ss)
{
    HANDLE h = ::CreateFile(peFile, GENERIC_READ,
        FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if(h == INVALID_HANDLE_VALUE)
    {
        return false;
    }

    DWORD dwSize = ::GetFileSize(h, NULL);
    DWORD dwReaded = 0;
    std::vector<BYTE> peBuf(dwSize);
    if(!::ReadFile(h, &peBuf[0], dwSize, &dwReaded, NULL))
    {
        return false;
    }

    return BuildSectCSum(&peBuf[0], sectName, ss);
}

} // namespace JoyGuard
